<?php
// Global =============================================================================
function cfgPath( $path ) {
	$tmp = str_ireplace('%Root', BASE_PATH, $path);
	$tmp = str_ireplace('%AppRoot', APP_PATH, $tmp);	
	$tmp = str_ireplace('.', DS, $tmp);

	return $tmp;
}

function fwimport( $path ) {
	//echo $path.'<br/>';
	if(file_exists( $path ))
	{
		require_once( $path );
		return true;
	}
	elseif(strpos($path, '.php') === false)
	{
		$realp = LIBS_PATH . DS . str_replace('.', DS, $path) . '.php';

		if(file_exists( $realp )):
			require_once( $realp );
			return true;
		endif;
	}

	trigger_error("<u>fwimport</u> couldn't load <b>$path</b>.<br/>", E_USER_WARNING);
	return false;
}

// Autoload ===========================================================================
function fwAutoload( $class_name ) {

	$prefix = substr($class_name, 0, strpos($class_name, '_'));
	
	if(empty( $prefix )) return;
	
	if(_isLib( $prefix )) 
	{
		_aLib( $class_name );
		return;
	}
	elseif(_isApp( $prefix )) 
	{
		_aApp( $class_name );
		return;
	}
	else
	{
		_aAny( $class_name );
		return;
	}
}

// Autoloadere ------------------------------------------------------------------------
function _aLib( $class_name,$get_path=false ) {
	
	$libs = loadfromCfg('libraries');

	$tokens = explode('_', $class_name);
	$prefix = array_shift( $tokens );
	
	foreach( $libs as $item ) {
		if($item->prefix == $prefix) {
			$loader = $item;
			break;
		}
	}
	
	if(empty( $loader )) return;

	$path = cfgPath($loader->path);
	
	foreach($tokens as $token) {
		$path .= DS . $token;
	}
	$path .= '.php';
	if($get_path): return substr($path,0,strrpos($path,end($tokens)));endif;

	fwimport( $path );
}

/** Autoloader pentru clase de tip aplicatie(care fac parte din aplicatie)
 * 
 * @param	String 	$class_name		Numele clasei
 * @param 	Boolean	$get_path		Util cand e folosita functia pentru a afla 
 * 									numele clasei si nu pentru a o importa 
 */
function _aApp($class_name, $get_path = false) {
	$apps = loadfromCfg('applications');
	$const = loadfromCfg('constants');

	$tokens = explode('_', $class_name);
	$prefix = array_shift($tokens);
	
	foreach( $apps as $item ) {
		if($item->prefix == $prefix) {
			$loader = $item;
		}
	}

	if(empty( $loader )) return;
	
	$path = cfgPath($loader->path);
	

	
	foreach($tokens as $order => $token) {
		switch($token) {
			case 'Controller': $path .= DS . $const['Default_Application_Controllers_Dir']; break;
			case 'Model'	 : $path .= DS . $const['Default_Application_Models_Dir'];		break;
			case 'View'		 : $path .= DS . $const['Default_Application_Views_Dir'];		break;
			case 'Table'	 : $path .= DS . $const['Default_Application_Tables_Dir'];		break; 
			case 'Helper'	 : $path .= DS . $const['Default_Application_Helpers_Dir'];		break;
			case 'Router'	 : break; // TODO: Check this out!! 
			case $const['Default_Application_EntryPoint_Name'] :
				$path .= DS . $token; break; 
			default	:
				switch( $order ) {
					case  0: $path .= DS . $const['Default_Application_Modules_Dir'] . DS . $token; break;
					default: $path .= DS . $token; break;
				}
		}
	}

	if(file_exists($path.".php")) 
	{
		// Daca fisierul exista, adaugam la final extensia
		// si il pregatim pentru importare
		$path .= ".php";
		
		// Daca avem `get_path` activat, trimitem calea;
		if($get_path): return substr($path, 0, strrpos($path, end($tokens))); endif;
		
		fwimport( $path );
	}
	else 
	{	// Autoloaderul dubleaza ultimul nume (token), permitand clasei cautate
		// sa fie stocata intr-un folder cu acelasi nume
		$path .= DS.end($tokens).".php";
		
		// Daca avem `get_path` activat, trimitem calea;
		if($get_path): return substr($path, 0, strrpos($path, end($tokens))); endif;
		
		//echo 'Autoloading class: '.$path;
		fwimport($path);
	}
}

function _aAny( $class_name,$get_path=false ) {
	$tokens = explode('_', $class_name);
	
	if( count($tokens) < 2 ) return;
	
	$path = BASE_PATH;
	foreach( $tokens as $token ) {
		$path .= DS . $token;
	}
	$path .= '.php';
	if($get_path): return substr($path,0,strrpos($path,end($tokens)));endif;	
	if(fwimport( $path ))
		trigger_error(	"Class <b>$class_name</b> loaded 
						from <u>undefined location</u>: $path.",
						E_USER_NOTICE	);
}

// Helpere pentru autoload ============================================================
function _isLib( $prefix, $refresh = false ) {
	// Primeste un prefix si verifica daca este librarie sau aplicatie
	static $libs_array;
	if(empty( $libs_array )) {
		$tmp = loadfromCfg('libraries', $refresh);
		$libs_array = array();
		foreach($tmp as $lib) {
			$libs_array[] = $lib->prefix;
		}
	}
	return in_array($prefix, $libs_array);
}

function _isApp( $prefix, $refresh = false ) {
	// Primeste un prefix si verifica daca este librarie sau aplicatie
	static $apps_array;
	if(empty( $apps_array )) {
		$tmp = loadfromCfg('applications', $refresh);
		$apps_array = array();
		foreach($tmp as $app) {
			$apps_array[] = $app->prefix;
		}
	}
	return in_array($prefix, $apps_array);
}

function loadfromCfg($type, $refresh = false ) 
{	// Incarca diverse elemente din configuratie pentru autoloader
	static $libraries;
	static $applications;
	static $constants;
	
	if(empty( ${$type} ) || $refresh) {
		global $framework;

		if($type == 'constants'):
			$constants = $framework->getConfig('constants');
			return $constants;
		elseif($type == 'applications' || $type == 'libraries'):
			$tmp = $framework->getConfig($type);
		else: return null;
		endif;

		${$type} = array();

		foreach($tmp as $item) {
			// Se creeaza un vector de obiecte, care vor avea numai proprietatile `name`, `prefix`, `path`
			$aux = new stdClass();
			$aux->name 	= $item->name;
			$aux->prefix= $item->prefix;
			$aux->path 	= $item->path;
			
			${$type}[ $aux->name ] = $aux;
		}
	}
	
	return ${$type};
}
